package datastructure.array;

/**
 * @Description: 自己封装的数组
 * @author: Yang Qiang
 * @create: 2021-11-02 21:28
 */
public class Array{
    // 数组
    private int[] data;
    // 当前数组的大小以及下一个元素添加的下标
    private int size;

    // 无参构造器, 初始化默认大小为10的数组
    public Array(){
        this(10);
    }

    // 有参构造
    public Array(int capictiy){
        this.data = new int[capictiy];
    }

    // 获取当前数组的元素个数
    public int getSize() {
        return size;
    }

    // 判断当前数组是否为null
    public boolean isEmpty(){
        return size == 0;
    }


    /**
     * 数组中间插入元素: 指定下标添加元素
     * @param index: 添加元素的下标位置
     * @param value: 添加的元素值
     */
    public void add(int index, int value){
        if (size == data.length){
            throw new RuntimeException("数组已满, 添加失败");
        }
        if (index < 0 || index > size){
            throw new RuntimeException("添加的下标必须大于等于0, 并且下标应该小于等于数组的最后元素下标, 因为数组需要保持连续");
        }

        // 移动位置(需要把添加位置的元素到最后一个元素全部往后移动一位)
        for (int i = size-1; i >=index ; i--){
            data[i+1] = data[i];
        }
        data[index] = value;
        size++;
    }

    /**
     * 往数组头部添加元素
     * @param value: 添加的元素
     */
    public void addFirst(int value){
        add(0,value);
    }

    /**
     * 往数组尾部添加元素
     * @param value: 添加的元素
     */
    public void addLast(int value){
        add(size, value);
    }


    /**
     * 修改指定下标的元素值
     * @param index: 需要修改的下标位置
     * @param value: 替换的值
     */
    public void set(int index, int value){
        if (index < 0 || index > size){
            throw new RuntimeException("修改失败: 下标应该大于等于0并且小于等于当前数组最后一个元素的下标");
        }
        data[index] = value;
    }

    /**
     * 在数组中查找指定数据的下标位置
     * @param value: 查找的元素值
     * @return
     */
    public int find(int value){
        for (int i = 0; i < size; i++) {
            if (data[i] == value){
                return i;
            }
        }
        return -1;
    }

    /**
     * 判断当前数组是否包含指定元素
     * @param value: 需要判断的值
     * @return: true包含, false不包含
     */
    public boolean contain(int value){
        for (int i = 0; i < size; i++) {
            if (data[i] == value){
                return true;
            }
        }
        return false;
    }


    /**
     * 删除指定位置的元素, 然后返回删除的元素
     * @param index
     * @return: 删除的元素值
     */
    public int remove(int index){
        if (index < 0 || index >= size){
            throw new RuntimeException("修改失败: 下标应该大于等于0并且小于当前数组最后一个元素的下标");
        }
        int ret = data[index];
        // 把删除位置后面的元素全部向前移动一位
        for (int i = index + 1; i < size ; i++) {
            data[i - 1] = data[i];
        }
        size--;
        return ret;
    }

    /**
     * 删除数组的第一个元素
     * @return 删除的元素值
     */
    public int removeFirst(){
        return remove(0);
    }

    /**
     * 删除数组的最后一个元素
     * @return 删除的元素值
     */
    public int removeLast(){
        return remove(size - 1);
    }

    /**
     * 删除指定元素
     * @param value: 需要删除的元素
     */
    public void removeValue(int value){
        int index = find(value);
        if (index != -1){
            remove(index);
        }
    }

    @Override
    public String toString() {

        StringBuilder res = new StringBuilder();
        res.append(String.format("Array: 元素个数 = %d, 长度 = %d\n", size, data.length));
        res.append("[");

        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if (i != size - 1){
                res.append(", ");
            }
        }
        res.append("]");
        return res.toString();
    }
}